package org.dromara.quick.chat.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.RandomUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.dubbo.config.annotation.DubboReference;
import org.dromara.common.core.exception.ServiceException;
import org.dromara.common.core.utils.IdGenerator;
import org.dromara.common.model.enums.channel.*;
import org.dromara.common.model.enums.groupuser.GroupMemberPermissionEnum;
import org.dromara.common.model.enums.groupuser.GroupMemberStatusEnum;
import org.dromara.common.model.enums.groupuser.MuteStatusEnum;
import org.dromara.common.redis.utils.RedisUtils;
import org.dromara.common.satoken.utils.LoginHelper;
import org.dromara.constant.CacheConstants;
import org.dromara.quick.chat.domain.*;
import org.dromara.quick.chat.mapper.ImGroupChatMapper;
import org.dromara.quick.chat.mapper.ImGroupMemberMapper;
import org.dromara.quick.chat.model.bo.create.ImGroupChatCreateBo;
import org.dromara.quick.chat.model.bo.query.ImGroupChatBo;
import org.dromara.quick.chat.model.vo.GroupChatUserInfoVO;
import org.dromara.quick.chat.model.vo.ImGroupChatDetailVO;
import org.dromara.quick.chat.model.vo.ImGroupChatVO;
import org.dromara.quick.chat.service.ImChannelService;
import org.dromara.quick.chat.service.ImChannelUserService;
import org.dromara.quick.chat.service.ImGroupChatService;
import org.dromara.quick.chat.service.ImGroupStatisticsService;
import org.dromara.resource.api.RemoteFileService;
import org.dromara.resource.api.domain.RemoteFile;
import org.dromara.system.api.RemoteUserService;
import org.dromara.utils.HanyuPinyinUtil;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.IOException;
import java.time.Duration;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 群聊表（群通讯录），记录群聊的相关信息及设置
* @author Stars
* @description 针对表【im_group_chat(群聊表（群通讯录），记录群聊的相关信息及设置)】的数据库操作Service实现
* @createDate 2025-03-04 22:33:21
*/
@Slf4j
@RequiredArgsConstructor
@Service
public class ImGroupChatServiceImpl extends ServiceImpl<ImGroupChatMapper, ImGroupChat>
    implements ImGroupChatService{

    /**
     * 群聊表
     */
    private final ImGroupChatMapper imGroupChatMapper;

    /**
     * 群成员关系表
     */
    private final ImGroupMemberMapper imGroupMemberMapper;

    /**
     * 频道表
     */
    private final ImChannelService imChannelService;

    /**
     * 频道用户表
     */
    private final ImChannelUserService imChannelUserService;

    /**
     * 群统计
     */
    private final ImGroupStatisticsService imGroupStatisticsService;

    /**
     * 资源服务
     * @param imGroupChatBo
     * @return
     */
    @DubboReference
    private final RemoteFileService remoteFileService;

    @DubboReference
    private final RemoteUserService remoteUserService;


    @Override
    public GroupChatUserInfoVO selectGroupChatInfo(Long groupId, Long userId) {
        GroupChatUserInfoVO cacheObject = RedisUtils.getCacheObject(CacheConstants.GROUP_CHAT_USER_INFO_KEY + groupId + userId);
        if (cacheObject != null){
            return cacheObject;
        }
        GroupChatUserInfoVO groupChatUserInfoVO = imGroupChatMapper.selectGroupChatInfo(groupId, userId);
        if (groupChatUserInfoVO != null){
            RedisUtils.setCacheObject(CacheConstants.GROUP_CHAT_USER_INFO_KEY+groupId+userId, groupChatUserInfoVO, Duration.ofHours(5));
        }
        return groupChatUserInfoVO;
    }

    @Override
    public List<ImGroupChatVO> selectGroupChatList(ImGroupChatBo imGroupChatBo) {
        Long userId = LoginHelper.getUserId();
        imGroupChatBo.setMemberId(userId);
        Page<ImGroupChat> page = new Page<>(imGroupChatBo.getPageNum(),imGroupChatBo.getPageSize());

        List<ImGroupChatVO> imGroupChatList = imGroupChatMapper.selectImGroupChatList(page, imGroupChatBo).getRecords();
        // 设置头像
        String avatars = imGroupChatList.stream().filter(f -> StringUtils.isNotEmpty(f.getGroupAvatar())).map(ImGroupChatVO::getGroupAvatar).collect(Collectors.joining(","));
        if (StringUtils.isNotEmpty(avatars)){
            List<RemoteFile> remoteFiles = remoteFileService.selectByIds(avatars);
            if (CollectionUtils.isNotEmpty(remoteFiles)){
                // 根据 ossId 字段将集合拆分成 Map
                Map<String, RemoteFile> remoteFilesMap = new HashMap<>();
                for (RemoteFile remoteFile : remoteFiles) {
                    remoteFilesMap.put(remoteFile.getOssId().toString(), remoteFile);
                }
                for (ImGroupChatVO imGroupChatVO : imGroupChatList) {
                    if (remoteFilesMap.containsKey(imGroupChatVO.getGroupAvatar())) {
                        imGroupChatVO.setGroupAvatar(remoteFilesMap.get(imGroupChatVO.getGroupAvatar()).getUrl());
                    }
                }
            }
        }
        return imGroupChatList;
    }

    @Override
    public ImGroupChatDetailVO searchGroupChat(Long id,String groupNumber) {
        ImGroupChatDetailVO imGroupChatSearchVO = imGroupChatMapper.selectImGroupChatDetail(id,groupNumber,LoginHelper.getUserId());
        if (imGroupChatSearchVO == null){
            return null;
        }
        if (imGroupChatSearchVO != null && StringUtils.isNotEmpty(imGroupChatSearchVO.getGroupAvatar())){
            String groupAvatar = remoteFileService.selectUrlByIds(imGroupChatSearchVO.getGroupAvatar());
            imGroupChatSearchVO.setGroupAvatar(groupAvatar);
        }
        // 查询群主信息
        imGroupChatSearchVO.setCreatorName(remoteUserService.selectNicknameById(imGroupChatSearchVO.getCreatorId()));
        return imGroupChatSearchVO;
    }

    @Transactional(rollbackFor = ServiceException.class)
    @Override
    public ImGroupChatVO createGroupChat(ImGroupChatCreateBo imGroupChatCreateBo) throws IOException {
        log.info("开始创建处理创建群业务逻辑，群名成为：{}", imGroupChatCreateBo.getGroupName());
        Long userId = LoginHelper.getUserId();
        Date date = new Date();
        ImGroupChat imGroupChat = new ImGroupChat();
        BeanUtil.copyProperties(imGroupChatCreateBo, imGroupChat);
        imGroupChat.setId(IdGenerator.getId());
        imGroupChat.setGroupNumber(this.groupNumberGenerator());
        imGroupChat.setInvitationConfirmation(imGroupChatCreateBo.getInvitationConfirmation());
        imGroupChat.setCreatorId(userId);
        imGroupChat.setCreateTime(date);
        imGroupChat.setGroupNamePinyin(new HanyuPinyinUtil().toHanyuPinyin(imGroupChatCreateBo.getGroupName()));
        imGroupChatMapper.insert(imGroupChat);
        log.info("数据已经添加到群表中，群id为：{}", imGroupChat.getId());
        ImGroupStatistics imGroupStatistics = new ImGroupStatistics();
        imGroupStatistics.setId(IdGenerator.getId());
        imGroupStatistics.setGroupId(imGroupChat.getId());
        imGroupStatistics.setTotalMembers(1);
        imGroupStatistics.setActiveMembers(1);
        imGroupStatisticsService.save(imGroupStatistics);
        log.info("群统计数据创建成功，群id为：{}", imGroupChat.getId());
        ImGroupMember imGroupMember = new ImGroupMember();
        imGroupMember.setId(IdGenerator.getId());
        imGroupMember.setGroupId(imGroupChat.getId());
        imGroupMember.setMemberId(userId);
        imGroupMember.setMemberPermission(GroupMemberPermissionEnum.GROUP_OWNER.getCode());
        imGroupMember.setGroupNote(imGroupChatCreateBo.getGroupNote());
        imGroupMember.setStatus(GroupMemberStatusEnum.ACCEPTED.getCode());
        imGroupMember.setIsMuted(MuteStatusEnum.UNMUTED.getCode());
        imGroupMember.setGroupNotePinYin(imGroupChat.getGroupNamePinyin());
        imGroupMember.setCreateTime(date);
        imGroupMemberMapper.insert(imGroupMember);
        log.info("数据已经添加到群成员表中，群id为：{}，群成员id为：{}", imGroupChat.getId(), imGroupMember.getId());
        ImChannel imChannel = new ImChannel();
        imChannel.setChannelId(imGroupChat.getId().toString());
        imChannel.setChannelType(ChannelTypeEnum.GROUP_CHANNEL.getCode());
        imChannel.setIsBanned(ChannelBanStatusEnum.NOT_BANNED.getCode());
        imChannel.setIsDeleted(ChannelDeleteStatusEnum.NOT_DELETED.getCode());
        imChannel.setCreateTime(date);
        imChannelService.createChannel(imChannel, userId);
        log.info("数据已经添加到频道表中，频道也是群id为：{}", imGroupChat.getId());

        ImChannelUser imChannelUser = new ImChannelUser();
        imChannelUser.setId(IdGenerator.getId());
        imChannelUser.setChannelId(imGroupChat.getId().toString());
        imChannelUser.setUserId(userId);
        imChannelUser.setIsBlacklist(ChannelBlacklistStatusEnum.NOT_IN_BLACKLIST.getCode());
        imChannelUser.setIsWhitelist(ChannelWhitelistStatusEnum.NOT_IN_WHITELIST.getCode());
        imChannelUser.setIsBanned(ChannelBanStatusEnum.NOT_BANNED.getCode());
        imChannelUser.setType(ChannelTypeEnum.GROUP_CHANNEL.getCode());
        imChannelUser.setCreateTime(date);
        imChannelUserService.addChannelUser(imChannelUser);
        log.info("数据已经添加到频道用户表中，群id为：{}，群组和用户关系表id:{}", imGroupChat.getId(), imChannelUser.getId());
        List<ImGroupChatVO> imGroupChatVOS = this.selectGroupChatList(ImGroupChatBo.builder().groupId(imGroupChat.getId()).build());
        if (CollectionUtils.isNotEmpty(imGroupChatVOS)) {
            return imGroupChatVOS.get(0);
        }
        return null;
    }

    @Override
    public ImGroupChat selectImGroupChatByGroupId(Long groupId) {
        if (groupId == null) {
            return null;
        }
        RedisUtils.getCacheObject(CacheConstants.CACHE_IM_GROUP_CHAT_KEY + groupId);
        // 查询群
        ImGroupChat imGroupChat = baseMapper.selectOne(new LambdaQueryWrapper<ImGroupChat>().in(ImGroupChat::getId, groupId));
        if (imGroupChat == null) {
            return null;
        }
        // 查询群头像
        String groupAvatar = remoteFileService.selectUrlByIds(imGroupChat.getGroupAvatar());
        // 更新群头像
        imGroupChat.setGroupAvatar(groupAvatar);
        if (imGroupChat != null) {
            RedisUtils.setCacheObject(CacheConstants.CACHE_IM_GROUP_CHAT_KEY + groupId, imGroupChat,Duration.ofHours(3));
        }
        return imGroupChat;
    }

    @Override
    public List<ImGroupChat> selectImGroupChatByGroupIds(List<Long> groupId) {
        if (CollectionUtils.isEmpty(groupId)) {
            return Collections.emptyList();
        }
        // 查询群
        List<ImGroupChat> groupIds = this.list(new LambdaQueryWrapper<ImGroupChat>().in(ImGroupChat::getId, groupId));
        // 提取 groupAvatar 属性并以逗号分隔
        String groupAvatars = groupIds.stream()
            .map(ImGroupChat::getGroupAvatar).distinct()
            .collect(Collectors.joining(","));
        // 查询群头像
        List<RemoteFile> remoteFiles = remoteFileService.selectByIds(groupAvatars);
        if (CollectionUtils.isNotEmpty(remoteFiles)) {
            // 将 RemoteFile 列表转换为 Map，方便查找
            Map<Long, String> ossIdToUrlMap = remoteFiles.stream()
                .collect(Collectors.toMap(RemoteFile::getOssId, RemoteFile::getUrl,
                    // 合并函数，这里选择保留现有的值
                    (existing, replacement) -> existing
                ));
            // 更新群头像
            groupIds.forEach(group -> {
                String ossIdStr = group.getGroupAvatar();
                if (StringUtils.isNotEmpty(ossIdStr)) {
                    Long ossId = Long.parseLong(ossIdStr);
                    if (ossIdToUrlMap.containsKey(ossId)) {
                        group.setGroupAvatar(ossIdToUrlMap.get(ossId));
                    }
                }
            });
        }
        return groupIds;
    }

    /**
     * 生成群号
     * @return
     */
    public String groupNumberGenerator() {
        // 生成一个长度为 11 的随机数字数组
        String groupNumber = RandomUtil.randomNumbers(11);
        // 查询该群号是否在使用
        if (imGroupChatMapper.exists(new LambdaQueryWrapper<ImGroupChat>().eq(ImGroupChat::getGroupNumber,groupNumber))) {
            this.groupNumberGenerator();
        }
        return groupNumber;
    }

}




